#include <ActorFactory.h>
#include <TransformComponent.h>
#include <MoveComponent.h>
#include <Actor.h>
#include <ActorComponent.h>
#include <TestComponent.h>
#include <RenderComponent.h>
#include <ALEstd.h>

ActorFactory::ActorFactory()
{
	m_lastActorId = INVALID_ACTOR_ID;
	m_actorComponentCreators[TestComponent::g_ID] = &CreateTestComponent;
	m_actorComponentCreators[TransformComponent2D::g_ID] = &CreateTransformComponent2D;
	m_actorComponentCreators[MoveComponent2D::g_ID] = &CreateMoveComponent2D;
	m_actorComponentCreators[SpriteComponent::g_ID] = &CreateSpriteComponent;
}

StrongActorPtr ActorFactory::CreateActor(const char* actorResource)
{
	tinyxml2::XMLDocument doc;
	doc.LoadFile(actorResource);

	tinyxml2::XMLElement* pRoot = doc.RootElement();

	if(!pRoot)
	{
		//TODO: error
		return StrongActorPtr();
	}

	StrongActorPtr pActor(ALE_NEW Actor(GetNextActorId()));
	if (!pActor->Init(pRoot))
	{
		return StrongActorPtr();
	}

	for (tinyxml2::XMLElement* pNode = pRoot->FirstChildElement(); pNode;
		pNode = pNode->NextSiblingElement())
	{
		StrongActorComponentPtr pComponent(VCreateComponent(pNode));
		if(pComponent)
		{
			pActor->AddComponent(pComponent);
			pComponent->SetOwner(pActor);
		}
		else
		{
			return StrongActorPtr();
		}
	}

	pActor->PostInit();

	return pActor;
}

StrongActorComponentPtr ActorFactory::VCreateComponent(tinyxml2::XMLElement* pData)
{
	std::string name(pData->Value());

	StrongActorComponentPtr pComponent;
	void* rawId = HashedString::hash_name(name.c_str());
	ComponentId id = reinterpret_cast<ComponentId>(rawId);
	auto findIt = m_actorComponentCreators.find(id);
	if(findIt != m_actorComponentCreators.end())
	{
		ActorComponentCreator creator = findIt->second;
		pComponent.reset(creator());
	}
	else
	{
		return StrongActorComponentPtr();
	}

	if(pComponent)
	{
		if(!pComponent->VInit(pData))
		{
			return StrongActorComponentPtr();
		}
	}

	return pComponent;
}
